package com.example.web_chat.config;

import com.example.web_chat.mapper.UserMapper;
import com.example.web_chat.model.*;
import com.example.web_chat.toolsUtil.Constant;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class WebSocketAPI extends TextWebSocketHandler {
    @Autowired
    private OnlineUserManage onlineUserManage;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    UserMapper userMapper;
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        //调用getAttributes获取到的是一个map，然后再根据key获取到session
        User user = (User)session.getAttributes().get(Constant.USER_SESSION);
        if(user == null) {
            System.out.println("用户未登录");
            return;
        }
        //把这个键值对存起来
        onlineUserManage.onLine(user.getUserId(), session);

    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        System.out.println("[webSocket收到消息]" + message.toString());
        User user = (User) session.getAttributes().get(Constant.USER_SESSION);
        if(user == null) {
            System.out.println("用户未登录,无法进行消息转发");
            return;
        }
        System.out.println("发送方user:" + user.toString());
        //1.通过message参数，获取到json字符串
        String messageString = message.getPayload();
        //2.把json字符串转换成 MessageRequest类的 Java对象
        MessageRequest req = objectMapper.readValue(messageString, MessageRequest.class);
        if (req.getType().equals("message")) {
            //进行消息转发
            transferMessage(user, req);
        }else {
            System.out.println("消息转发失败,req的type不是message");
        }

    }

    //通过这个方法来进行消息的转发
    //第一个参数表示要转发的消息是从谁哪来的
    //第二个参数是发来的请求，从请求中获取内容并构造响应
    public void transferMessage(User fromUser, MessageRequest request) throws IOException {
        //1. 构造一个MessageResponse对象，用于后续的传输
        //2. 根据请求中的sessionId查询数据库，得到这个聊天会话中有哪些用户
        //3. 循环遍历上述查询到的所有用户，给每个用户都发送一个MessageResponse
        //   根据查询到的userId，就可以查询OnlineUserManage,得到每一个用户的webSocketSession
        //   进而发送消息
        //注意：这里除了给会话中的用户们发送以外，还需要给自己也发送一份，以便在自己的客户端也可以查看到自己发送的消息
        //注意：一个会话中，是可以支持群聊的，虽然在前端没有实现群聊逻辑，但是在后端这里，实现了可以群聊的功能，所以，这里
        // 的转发逻辑也要能够实现群聊
        // 转发的消息还要保存在数据库中，等到用户下次再登录时，能够获取到历史消息

        //1)
        MessageResponse resp = new MessageResponse();
        resp.setFromId(fromUser.getUserId());//发送者的id
        resp.setFromName(fromUser.getUsername());//发送者的名字
        resp.setSessionId(request.getSessionId());//会话id
        resp.setContent(request.getContent());//发送的内容
        //这是一个Java对象，要想转发，还需要转成json字符串
        String respJson = objectMapper.writeValueAsString(resp);
        System.out.println("[transferMessage] respJson:" + respJson);

        //2)
        List<Friend> friends = userMapper.queryFriendBySessionId(request.getSessionId(), fromUser.getUserId());
        //因为sql语句把自己给排除了，所以要再构造一个自己的，后续给自己也发一份，在自己的客户端上也进行显示。
        Friend friendMysel = new Friend();
        friendMysel.setFriendId(fromUser.getUserId());
        friendMysel.setFriendName(fromUser.getUsername());
        friends.add(friendMysel);
        log.info("friends:{}", friends);
        //3)
        for(Friend friend : friends) {
            //根据查询到的userId，就可以查询OnlineUserManage,得到每一个用户的webSocketSession
            //因为一个会话里可能不止一个人(群聊)，所以要遍历的获取到每个人的userId，根据给每个人userId获取到对应的WebSocketSession，给每个人都发送一个消息
            WebSocketSession webSocketSession = onlineUserManage.getWebSocketSession(friend.getFriendId());
            if(webSocketSession == null) {
                System.out.println("当前用户的webSocketSession为空:" + friend.getFriendName());
                //如果该用户不在线，则不发送，但是需要把消息保存在数据库中
                continue;
            }
            webSocketSession.sendMessage(new TextMessage(respJson));
//            //发送消息
//            webSocketSession.sendMessage(new TextMessage(respJson));
//            //将转发的消息保存在数据库中
//            Message message = new Message();
//            message.setFromId(friend.getFriendId());
//            message.setSessionId(request.getSessionId());
//            message.setContent(request.getContent());
//            Integer addRet = userMapper.add(message);
//            if(addRet < 1) {
//                System.out.println("数据库保存转发消息失败");
//                return;
//            }

        }
        //发送消息
        //将转发的消息保存在数据库中
        Message message = new Message();
        message.setFromId(resp.getFromId());
        message.setSessionId(resp.getSessionId());
        message.setContent(resp.getContent());
        Integer addRet = userMapper.add(message);
        if(addRet < 1) {
            System.out.println("数据库保存转发消息失败");
            return;
        }
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        System.out.println("连接异常:" + exception.toString());
       User user  = (User)session.getAttributes().get(Constant.USER_SESSION);
       if(user == null) {
           System.out.println("用户不存在，断开连接异常");
           return;
       }
       onlineUserManage.unLine(user.getUserId(), session);
        System.out.println("[" + user.getUserId() + "] 连接断开");

    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        User user  = (User)session.getAttributes().get(Constant.USER_SESSION);
        if(user == null) {
            System.out.println("用户不存在，断开连接异常");
            return;
        }
        onlineUserManage.unLine(user.getUserId(), session);
        System.out.println("[" + user.getUserId() + "] 连接断开");

    }
}
